package org.geekbang.thinking.in.spring.configuration.metadata;

import org.geekbang.thinking.in.spring.ioc.overview.domain.User;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.util.ObjectUtils;

/**
 * Bean 配置元信息示例
 *
 * @author wangyh2
 * @version v1.0
 * @since 2021-10-18 15:37
 */
public class BeanConfigurationMetadataDemo {
    public static void main(String[] args) {
        // 1, BeanDefinition 的定义（声明）
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);
        beanDefinitionBuilder.addPropertyValue("name", "sishen007");
        // 2, 获取 AbstractBeanDefinition
        AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
        // 3, 附加属性（不影响 Bean populate、initialize）
        beanDefinition.setAttribute("name", "sishen008");
        // 4, 附加 ： 当前 BeanDefinition 来自于何方（辅助作用）
        beanDefinition.setSource(BeanConfigurationMetadataDemo.class);
        // 5, DefaultListableBeanFactory 并注册 beanDefinition
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        // 6, addBeanPostProcessor
        beanFactory.addBeanPostProcessor(new BeanPostProcessor() {
            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                if (ObjectUtils.nullSafeEquals("user", beanName) && User.class.equals(bean.getClass())) {
                    BeanDefinition bd = beanFactory.getBeanDefinition("user");
                    if (BeanConfigurationMetadataDemo.class.equals(bd.getSource())) {
                        User user = (User) bean;
                        user.setName((String) bd.getAttribute("name"));
                    }
                }
                return bean;
            }
        });
        // 7, 注册 User 的 BeanDefinition
        beanFactory.registerBeanDefinition("user", beanDefinition);
        // 8, 获取 user bean
        User user = beanFactory.getBean("user", User.class);
        // 9, 打印
        System.out.println(user);
    }
}
